<?php
// Utilities for finding files. Heavy-weight script so don't use for pages but useful for deployment.
// Part of mmvc library, https://code.google.com/p/mmvc/
// Dependencies: None

define( 'MMVC_OS_IS_WINDOWS_NT', getenv('OS')=='Windows_NT' );

/**
 * Returns file name with all '\' characters replaced with '/'
 */
function normalizePathName( $f )
{
	return str_replace( '\\', '/', $f );
}

/**
 * Returns file name with all '/' and '\\' characters replaced 
 * with native path seprator.
 */
function pathNameToNative( $f )
{
	if ( getenv('OS') == 'Windows_NT' ) {
		$from = '/';
		$to = '\\';
	}
	else {
		$from = '\\';
		$to = '/';
	}
	return str_replace( $from, $to, $f );
}

/**
 * Normalizes and joins two path names together.
 * For example, joinPathName("C:\\myfolder","subdir") returns "C:/myfolder/subdir"
 */
function joinPathName( $a, $b ) {
	$a = normalizePathName($a);
	$b = normalizePathName($b);
	return substr($a,-1)=='/' ? $a.$b : $a.'/'.$b;
}

/*
 * Implementation function of pregFindFiles.
 * Finds files recursively under current working directory using regular expression pattern matching to file name.
 * @param $pattern Pattern to find. See preg_match
 * @param $list Array of full path names
 * @param $recurse Recurse subdirs. Default is true.
 * @see pregFindFiles
 */
function pregFindFilesR( $pattern, &$list, $recurse=true )
{
	$files = scandir( '.' );
	$dirs = array();
	foreach ($files as $file)
	{
		if ( $file != '.' && $file != '..' )
		{
			if ( is_dir($file) )
			{
				$dirs[] = normalizePathName($file);
			}
			//else // allow also dirs to be matched
			{
				$file_lc = (MMVC_OS_IS_WINDOWS_NT ? mb_strtolower($file,'UTF-8') : $file);
				if ( 1 == preg_match($pattern,$file_lc) )
				{
					$list[] = normalizePathName( realpath( $file ) );
				}
			}
		}
	}

	if ($recurse)
	{
		foreach ($dirs as $dir)
		{
			chdir( $dir );
			pregFindFilesR( $pattern, $list );
			chdir( '..' );
		}
	}
	
	return $list;
}

/**
 * Finds files recursively under specified directory using regular expression pattern matching to file name.
 * @param $pattern Pattern to find. See preg_match
 * @param $dir Directory to start in. Default is current working directory.
 * @param $recurse Recurse subdirs. Default is true.
 * @return List of absolute file names found or false on error
 */
function pregFindFiles( $pattern, $dir='.', $recurse=true )
{
	$cwd = getcwd();
	if ( !chdir($dir) )
		return false;
	$list = array();
	pregFindFilesR( $pattern, $list );
	chdir( $cwd );
	return $list;
}

/**
 * Finds files recursively. Supports wildcards.
 * On Windows file names are matches as lower case.
 * Example: findFiles("*.php") or findFiles( array("*.php", "*.phtml") )
 * @param $fname array or file path/name using wildcards.
 * @param $recurse Recurse subdirs. Default is true.
 * @return List of absolute file names found or false on error
 */
function findFiles( $fnames, $recurse=true )
{
	$arr_files = array();
	if ( is_array( $fnames ) )
		$arr_files = $fnames;
	else
		array_push( $arr_files, $fnames );
		
	$result = array();
	
	foreach ( $arr_files as $fname )	
	{
		assert( strpos($fname,'|') === false ); // '|' not allowed in file names since it's used for regex
		assert( strpos($fname,'?') === false ); // '?' not allowed in file names since it's used for regex

		$fname = normalizePathName( $fname );
		$repl = array(
			'.' => '\.',
			'*' => '.*',
			'?' => '.',
		);
		$pattern = basename($fname);
		foreach ($repl as $s => $d)
			$pattern = str_replace($s,$d,$pattern);
		$pattern = '|^'.$pattern.'$|';
		
		$result = array_merge( $result, pregFindFiles( $pattern, dirname($fname), $recurse ));
	}
	
	return $result;
}

/**
 * Finds all gettext-style string literals __('Hello, world!') from content.
 * @return Array of strings to localize
 */
function findLocalizationStringsFromContent( $content ) {
	$len = strlen($content);
	preg_match_all('|[^\w]__\s*\(\s*|', $content, $m, PREG_OFFSET_CAPTURE );
	$m = $m[0];
	$strings = array();
	foreach ($m as $e) {
		$begin = $e[1]+strlen($e[0])+1;
		$term = substr( $content, $begin-1, 1 );
		if ($term != '"' && $term != "'")
			continue;
		$end = $begin+1;
		while ( $end < $len ) {
			$ch = substr($content,$end,1);
			if ( $ch == '\\' ) {
				$end += 2;
				continue;
			}
			if ( $ch == $term )
				break;
			++$end;
		}
		if ($end-$begin > 1)
			$strings[] = substr($content,$begin,$end-$begin);
	}
	return $strings;
}

/**
 * Finds all gettext-style string literals __('Hello, world!') from files.
 * @param $fnames Array of file names to search
 * @return Array of strings to localize
 */
function findLocalizationStringsFromFiles( $fnames ) {
	$out = array();
	foreach ($fnames as $fname) {
		$content = file_get_contents( $fname );
		$out = array_merge( $out, findLocalizationStringsFromContent($content) );
	}
	sort($out);
	$out = array_unique($out);
	//print_r($out);
	return $out;
}

?>